home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hot Super Models
/
Hot Super Models.iso
/
unix
/
x11
/
xv200.tar
/
xv-2.00
/
unsupt
/
vicar
< prev
next >
Wrap
Text File
|
1992-01-01
|
78KB
|
2,148 lines
(Message /usr/users/bradley/Mail/inbox:27)
Return-Path: datri@lovecraft.convex.com
Received-Date: Tue, 29 Oct 91 15:06:28 EST
Received: from convex.convex.com by central.cis.upenn.edu
id AA26939; Tue, 29 Oct 91 15:06:07 -0500
Posted-Date: Tue, 29 Oct 1991 14:03:52 -0600 (CST)
Received: from lovecraft.convex.com by convex.convex.com (5.61/1.35)
id AA23755; Tue, 29 Oct 91 14:03:55 -0600
Received: by lovecraft.convex.com (4.1/SMI-4.1)
id AA26110; Tue, 29 Oct 91 14:03:53 CST
Received: from Messages.7.15.N.CUILIB.3.45.SNAP.NOT.LINKED.lovecraft.convex.com.sun4.41
via MS.5.6.lovecraft.convex.com.sun4_41;
Tue, 29 Oct 1991 14:03:52 -0600 (CST)
Message-Id: <wd3Pucm2e4NhRWUuI=@concave>
Date: Tue, 29 Oct 1991 14:03:52 -0600 (CST)
From: "Anthony A. Datri" <datri@concave.convex.com>
To: bradley@central.cis.upenn.edu
Subject: xv
I hear that you're intested in my additions to xv after all. There's a
tar file of the whole thing on convex.com for anonymous ftp, and here
are the diffs that I think should work.
Add a line to the Makefile like
# if you don't have strstr, uncomment this
STRSTRF = #-DNOSTRSTR
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by lovecraft!datri on Tue Oct 29 13:59:32 CST 1991
# Contents: diff pds.h pdsuncomp.c xvpds.c
echo x - diff
sed 's/^@//' > "diff" <<'@//E*O*F diff//'
diff -c pristine/xv.c xv/xv.c
*** pristine/xv.c Thu Nov 29 12:44:53 1990
--- xv/xv.c Tue Sep 3 13:50:45 1991
***************
*** 53,58 ****
--- 53,59 ----
#define PM 2
#define PBM 3
#define XBM 4
+ #define PDS 5
static unsigned long rootbg, rootfg; /* fg/bg for root border */
static int waitsec = -1; /* seconds between pics. -1=wait for event */
***************
*** 785,791 ****
else if (magicno[0] == 'P' && magicno[1]>='1' &&
magicno[1]<='6') filetype = PBM;
! else if (strncmp(magicno,"#define",7)==0) filetype = XBM;
if (filetype == UNKNOWN) {
SetISTR(ISTR_INFO,"'%s' not in a recognized format.", basename);
--- 786,798 ----
else if (magicno[0] == 'P' && magicno[1]>='1' &&
magicno[1]<='6') filetype = PBM;
! /* this doesn't *really* detect the full magic, since the above
! code only reads 8 bytes */
! else if (strncmp(magicno,"NJPL1I00",8)==0 ||
! strncmp(magicno+2,"NJPL1I",6)==0 ||
! strncmp(magicno,"LBLSIZE=",8)==0) {
! filetype = PDS;
! } else if (strncmp(magicno,"#define",7)==0) filetype = XBM;
if (filetype == UNKNOWN) {
SetISTR(ISTR_INFO,"'%s' not in a recognized format.", basename);
***************
*** 800,805 ****
--- 807,813 ----
case PM: i = LoadPM (filename,ncols); break;
case PBM: i = LoadPBM(filename,ncols); break;
case XBM: i = LoadXBM(filename,ncols); break;
+ case PDS: i = LoadPDS(filename,ncols); break;
}
WaitCursor();
diff -c pristine/xv.h xv/xv.h
*** pristine/xv.h Thu Nov 29 12:45:35 1990
--- xv/xv.h Fri Sep 6 10:37:04 1991
***************
*** 38,45 ****
#endif
/* neither IBM AOS 4.3, Convex, nor BSD 4.3 on VAX have <malloc.h> */
! #if !defined(ibm032) && !defined(__convexc__) && \
! !(defined(vax) && !defined(ultrix))
#if defined(hp300) || defined(hp800)
#include <sys/malloc.h> /* it's in 'sys' on HPs*/
#else
--- 38,44 ----
#endif
/* neither IBM AOS 4.3, Convex, nor BSD 4.3 on VAX have <malloc.h> */
! #if !defined(ibm032) && !defined(__convexc__) && !(defined(vax) &&
!defined(ultrix))
#if defined(hp300) || defined(hp800)
#include <sys/malloc.h> /* it's in 'sys' on HPs*/
#else
***************
*** 558,567 ****
int LoadXBM(char *, int);
int WriteXBM(FILE *, byte *, int, int, char *);
-
-
-
#else /* using non-ANSI cc. Function defs, but no params */
--- 557,565 ----
int LoadXBM(char *, int);
int WriteXBM(FILE *, byte *, int, int, char *);
+ /**************************** XVPDS.C ***************************/
+ int LoadPDS(char *, int);
#else /* using non-ANSI cc. Function defs, but no params */
***************
*** 632,636 ****
--- 630,636 ----
/**************************** XVXBM.C ***************************/
int LoadXBM(), WriteXBM();
+ /**************************** XVPDS.C ***************************/
+ int LoadPDS();
#endif
@//E*O*F diff//
chmod u=rw,g=r,o=r diff
echo x - pds.h
sed 's/^@//' > "pds.h" <<'@//E*O*F pds.h//'
#define PDSFIXED (1)
#define PDSVARIABLE (2)
#define PDSTRASH (-1)
#define VICAR (3)
@//E*O*F pds.h//
chmod u=rw,g=r,o=r pds.h
echo x - pdsuncomp.c
sed 's/^@//' > "pdsuncomp.c" <<'@//E*O*F pdsuncomp.c//'
/* datri@convex.com, 4-14-91
This file is taken almost unchanged from the NASA CD-ROMS of the Voyager
images. I can find no copyright anywhere near this code.
All I've done is added - as a special case for the output
filename to go to stdout, and made informational messages go to stderr
instead of stdout, removing some of the silly ones. I've also corrected
some of the places where fools assume that VAX and VMS are synonymous */
/********************************************************************/
/* Voyager Image Decompression Program - C Version for PC, VAX, */
/* UNIX and Macintosh systems. */
/* */
/* Decompresses images using Kris Becker's subroutine DECOMP.C */
/* which is included in this program in a shortened version. */
/* */
/* Reads a variable length compressed VOYAGER image and outputs a */
/* fixed length uncompressed image file in PDS format with */
/* labels, image histogram, engineering table and 800 lines of */
/* 836 bytes (800 samples, 36 engineering bytes); or an 800 by */
/* 800 array with FITS, VICAR or no labels. If used on a non- */
/* byte-swapped machine the image histogram is un-swapped. */
/* */
/********************************************************************/
/* */
/* Use the following commands to compile and link to produce an */
/* executable file: */
/* */
/* On an IBM PC (using Microsoft C Version 5.x) */
/* */
/* cl /c cdcomp.c */
/* link cdcomp/stack:10000; */
/* */
/* On a VAX: */
/* */
/* cc cdcomp */
/* $define lnk$library sys$library:vaxcrtl.olb */
/* link cdcomp */
/* */
/* On a Unix host (Sun, Masscomp) */
/* */
/* cc -o cdcomp cdcomp.c */
/* */
/* On a Macintosh (using Lightspeed C) */
/* */
/* link with the following libraries: */
/* stdio, storage, strings, unix and MacTraps, with MacTraps */
/* in a separate segment. */
/* */
/********************************************************************/
/* */
/* Use the following command to run the program: */
/* */
/* CDCOMP [infile] [outfile] [output format] */
/* */
/* infile - name of compressed image file. */
/* outfile - name of uncompressed output file. */
/* output format - selected from the following list: */
/* */
/* 1 SFDU/PDS format [DEFAULT]. */
/* 2 FITS format. */
/* 3 VICAR format. */
/* 4 Unlabelled binary array. */
/* */
/* Under VMS you will need to 'install' the program to */
/* be able to use command line arguments using the following */
/* command: */
/* */
/* $ vaxdcomp :== $DISKNAME:[DIRECTORY]vaxcomp.exe */
/* */
/* where DISKNAME is the disk drive and DIRECTORY is the */
/* directory where VAXDCOMP.EXE is stored. */
/* */
/********************************************************************/
/* */
/* LIMS */
/* This program has been tested on a VAX 780 (VMS 4.6), SUN */
/* Workstation (UNIX 4.2, release 3.4), an IBM PC */
/* (MICROSOFT 5.1 compiler) and Macintosh IIx using Lightspeed C */
/* version 3.0. When converting to other systems, check for */
/* portability conflicts. */
/* */
/* HIST */
/* AUG89 Added code to get command line arguments for filenames */
/* and output format; routines to free memory used by the Huffman */
/* tree); fixed the SFDU label output length; and modified the */
/* I/O routines so that the open for Host type 2 uses binary I/O. */
/* JUN89 Fixed READVAR, to get length on 16-bit unswapped hosts. */
/* JUL88 C driver to decompress standard Voyager Compressed images */
/* by Mike Martin 1989/06/10 */
/* */
/* Inputs - Input file to be decompressed. */
/* */
/* Outputs - Output file containing decompressed image. */
/* */
/********************************************************************/
#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define RECORD_BYTES 836
/* pc i/o defines */
#define O_RDONLY 0x0000 /* open for reading only */
#define O_BINARY 0x8000 /* file mode is binary */
/* vax i/o defines */
#define RECORD_TYPE "rfm=fix" /* VMS fixed length output */
#define CTX "ctx=bin" /* no translation of \n */
#define FOP "fop=cif,sup" /* file processing ops */
typedef struct leaf
{
struct leaf *right;
short int dn;
struct leaf *left;
} NODE;
/*************************************************************************
Declare the tree pointer. This pointer will hold the root of the tree
once the tree is created by the accompanying routine huff_tree.
**************************************************************************/
NODE *tree;
/* subroutine definitions */
void pds_labels();
void fits_labels();
void vicar_labels();
void no_labels();
int check_host();
int get_files();
long swap_long();
void decompress();
void decmpinit();
void free_tree();
/* global variables */
int infile,Argc;
FILE *outfile;
char inname[80],outname[80];
int output_format;
main(argc,argv)
int argc;
char **argv;
{
char ibuf[2048],obuf[2048];
unsigned char blank=32;
short host,length,total_bytes,line,i;
long long_length,hist[511];
int out_bytes = RECORD_BYTES;
int count;
/*********************************************************************/
/* */
/* get host information and input and output files */
/* */
/*********************************************************************/
Argc=argc;
strcpy(inname," ");
strcpy(outname," ");
output_format = 0;
if (argc == 1); /* prompt user for parameters */
else if (argc == 2 && (strncmp(argv[1],"help",4) == 0 ||
strncmp(argv[1],"HELP",4) == 0 ||
strncmp(argv[1],"?",1) == 0))
{
fprintf(stderr,"Voyager Image Decompression Program. Command line
format:\n\n");
fprintf(stderr,"CDCOMP [infile] [outfile] [format code]\n");
fprintf(stderr," infile - name of compressed image file.
\n");
fprintf(stderr," outfile - name of uncompressed output
file. \n");
fprintf(stderr," output format - selected from the following
list: \n");
fprintf(stderr,"
\n");
fprintf(stderr," 1 SFDU/PDS format [DEFAULT].
\n");
fprintf(stderr," 2 FITS format.
\n");
fprintf(stderr," 3 VICAR format.
\n");
fprintf(stderr," 4 Unlabelled binary array.
\n\n");
exit(1);
}
else
{
strcpy(inname,argv[1]);
if (argc >= 3) strcpy(outname,argv[2]);
if (argc == 3) output_format = 1;
if (argc == 4) sscanf(argv[3],"%d",&output_format);
}
host = check_host();
host = get_files(host); /* may change host if VAX */
/*********************************************************************/
/* */
/* read and edit compressed file labels */
/* */
/*********************************************************************/
switch (output_format)
{
case 1: pds_labels(host);
break;
case 2: fits_labels(host);
break;
case 3: vicar_labels(host);
break;
case 4: no_labels(host);
}
/*********************************************************************/
/* */
/* process the image histogram */
/* */
/*********************************************************************/
/* need to know record_bytes,hist_count,hist_item_type,item_count.*/
total_bytes = 0;
length = read_var((char *)hist,host);
total_bytes = total_bytes + length;
length = read_var((char *)hist+836,host);
total_bytes = total_bytes + length;
if (host == 2 || host == 5) /* If non-byte swapped */
for (i=0;i<256;i++) /* host, swap bytes in */
hist[i] = swap_long(hist[i]); /* the output histogram */
if (output_format == 1)
{
fwrite((char *)hist, 836,1,outfile);
fwrite((char *)hist+836,length,1,outfile);
/* pad out the histogram to a multiple of RECORD_BYTES */
for (i=total_bytes;i<RECORD_BYTES*2;i++) fputc(blank,outfile);
}
/*********************************************************************/
/* */
/* process the encoding histogram */
/* don't have to byte-swap because DECOMP.C does it for us */
/* */
/*********************************************************************/
length = read_var((char *)hist,host);
length = read_var((char *)hist+836,host);
length = read_var((char *)hist+1672,host);
/*********************************************************************/
/* */
/* process the engineering summary */
/* */
/*********************************************************************/
total_bytes = 0;
length = read_var(ibuf,host);
if (output_format == 1)
{
fwrite(ibuf,length,1,outfile);
total_bytes = total_bytes + length;
/* pad out engineering to multiple of 836 */
for (i=total_bytes;i<RECORD_BYTES;i++) fputc(blank,outfile);
}
/*********************************************************************/
/* */
/* initialize the decompression */
/* */
/*********************************************************************/
/*stupid fprintf(stderr,"\nInitializing decompression routine..."); */
decmpinit(hist);
/*********************************************************************/
/* */
/* decompress the image */
/* */
/*********************************************************************/
/* stupid
printf("\nDecompressing data..."); */
line=0;
do
{
length = read_var(ibuf,host);
if (length <= 0) break;
long_length = (long)length;
line += 1;
decompress(ibuf, obuf,&long_length, &out_bytes);
if (output_format == 1)
{
count = fwrite(obuf,RECORD_BYTES,1,outfile);
if (count != 1)
{
fprintf(stderr,"\nError writing output file. Aborting program.");
fprintf(stderr,"\nCheck disk space or for duplicate file
name (VMS).");
exit(1);
}
}
else fwrite(obuf,800,1,outfile);
/* stupid if (line % 100 == 0) printf("\n line %d",line);*/
} while (length > 0 && line < 800);
/* pad out FITS file to a multiple of 2880 */
if (output_format == 2)
for (i=0;i<2240;i++) fputc(blank,outfile);
/*stupid printf("\n");*/
free_tree(&long_length);
close(infile);
fclose(outfile);
}
/*********************************************************************/
/* */
/* subroutine get_files - get input filenames and open */
/* */
/*********************************************************************/
int get_files(host)
int host;
{
short shortint;
if (inname[0] == ' ')
{
fprintf(stderr,"\nEnter name of file to be decompressed: ");
gets (inname);
}
if (host == 1 | host == 2)
{
if ((infile = open(inname,O_RDONLY | O_BINARY)) <= 0)
{
fprintf(stderr,"\ncan't open input file: %s\n",inname);
exit(1);
}
}
else if (host == 3 | host == 5)
{
if ((infile = open(inname,O_RDONLY)) <= 0)
{
fprintf(stderr,"\ncan't open input file: %s\n",inname);
exit(1);
}
/****************************************************************/
/* If we are on a vax see if the file is in var length format. */
/* This logic is in here in case the vax file has been stored */
/* in fixed or undefined format. This might be necessary since */
/* vax variable length files can't be moved to other computer */
/* systems with standard comm programs (kermit, for example). */
/****************************************************************/
if (host == 3)
{
read(infile,&shortint,2);
if (shortint > 0 && shortint < 80)
{
host = 4; /* change host to 4 */
fprintf(stderr,"This is not a VMS variable length file.");
}
else fprintf(stderr,"This is a VMS variable length file.");
lseek(infile,0,0); /* reposition to beginning of file */
}
}
if (output_format == 0)
do
{
fprintf(stderr,"\nEnter a number for the output format desired:\n");
fprintf(stderr,"\n 1. SFDU/PDS format.");
fprintf(stderr,"\n 2. FITS format.");
fprintf(stderr,"\n 3. VICAR format.");
fprintf(stderr,"\n 4. Unlabelled binary array.\n");
fprintf(stderr,"\n Enter format number:");
gets(inname);
output_format = atoi(inname);
} while (output_format < 1 || output_format > 4);
if (outname[0] == ' ')
{
fprintf(stderr,"\nEnter name of uncompressed output file: ");
gets (outname);
}
if (*outname == '-') { /* write to stdout */
outfile = stdout;
return(host);
}
if (host == 1 || host == 2 || host == 5)
{
if ((outfile = fopen(outname,"wb"))==NULL)
{
fprintf(stderr,"\ncan't open output file: %s\n",outname);
exit(1);
}
}
/* ANSI C doesn't like the extra crappy arguments to fopen below */
#ifndef __unix__
else if (host == 3 || host == 4)
{
if (output_format == 1) /* write PDS format blocks */
{
if ((outfile=fopen(outname,"w",
"mrs=836",FOP,CTX,RECORD_TYPE))==NULL)
{
fprintf(stderr,"\ncan't open output file: %s\n",outname);
exit(1);
}
}
else if (output_format == 2) /* write FITS format blocks */
{
if ((outfile=fopen(outname,"w",
"mrs=2880",FOP,CTX,RECORD_TYPE))==NULL)
{
fprintf(stderr,"\ncan't open output file: %s\n",outname);
exit(1);
}
}
else /* write 800 byte records */
{
if ((outfile=fopen(outname,"w",
"mrs=800",FOP,CTX,RECORD_TYPE))==NULL)
{
fprintf(stderr,"\ncan't open output file: %s\n",outname);
exit(1);
}
}
}
#endif
return(host); /* In case its been updated */
}
/*********************************************************************/
/* */
/* subroutine pds_labels - edit PDS labels and write to output file */
/* */
/*********************************************************************/
void pds_labels(host)
int host;
{
char outstring[80],ibuf[2048];
unsigned char cr=13,lf=10,blank=32;
short length,nlen,total_bytes,line,i;
total_bytes = 0;
do
{
length = read_var(ibuf,host);
ibuf[length]=NULL;
/******************************************************************/
/* edit labels which need to be changed */
/******************************************************************/
if ((i = strncmp(ibuf,"NJPL1I00PDS1",12)) == 0)
/*****************************************************************/
/* add the output file length to the sfdu label */
/*****************************************************************/
{
strcpy(outstring,ibuf);
strcpy(outstring+12,"00673796");
strcpy(outstring+20,ibuf+20);
fwrite(outstring,length,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + length + 2;
}
else if ((i = strncmp(ibuf,"RECORD_TYPE",11)) == 0)
/*****************************************************************/
/* change the record_type value from variable to fixed */
/*****************************************************************/
{
strcpy(ibuf+35,"FIXED_LENGTH");
length = length - 3;
fwrite(ibuf,length,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + length + 2;
}
else if ((i = strncmp(ibuf,"FILE_RECORDS",12)) == 0)
/*****************************************************************/
/* change the file_records count to 806 */
/*****************************************************************/
{
strcpy(ibuf+35,"806");
fwrite(ibuf,length,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + length + 2;
}
else if ((i = strncmp(ibuf,"LABEL_RECORDS",13)) == 0)
/*****************************************************************/
/* change the label_records count from 56 to 3 */
/*****************************************************************/
{
strcpy(ibuf+35,"3");
length -= 1;
fwrite(ibuf,length,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + length + 2;
}
else if ((i = strncmp(ibuf,"^IMAGE_HISTOGRAM",16)) == 0)
/*****************************************************************/
/* change the location pointer of image_histogram to record 4 */
/*****************************************************************/
{
strcpy(ibuf+35,"4");
length -= 1;
fwrite(ibuf,length,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + length + 2;
}
else if ((i = strncmp(ibuf,"^ENCODING_HISTOGRAM)",19)) == 0);
/*****************************************************************/
/* delete the encoding_histogram location pointer */
/*****************************************************************/
else if ((i = strncmp(ibuf,"^ENGINEERING_TABLE",18)) == 0)
/*****************************************************************/
/* change the location pointer of engineering_summary to record 6*/
/*****************************************************************/
{
strcpy(ibuf+35,"6");
length -= 1;
fwrite(ibuf,length,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + length + 2;
}
else if ((i = strncmp(ibuf,"^IMAGE",6)) == 0)
/*****************************************************************/
/* change the location pointer of image to record 7 */
/*****************************************************************/
{
strcpy(ibuf+35,"7");
length = length -1;
fwrite(ibuf,length,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + length + 2;
}
else if ((i = strncmp(ibuf,
"OBJECT = ENCODING",43)) == 0)
/*****************************************************************/
/* delete the 4 encoding histogram labels */
/*****************************************************************/
{
for (i=0;i<4;i++) /* ignore these labels */
{
length = read_var(ibuf,host);
}
}
else if ((i = strncmp(ibuf," ENCODING",9)) == 0);
/*****************************************************************/
/* delete the encoding type label in the image object */
/*****************************************************************/
else if ((host == 2 || host == 5) && (i = strncmp(ibuf,
" ITEM_TYPE = VAX_INTEGER",46)) == 0)
/*****************************************************************/
/* change the record_type value from variable to fixed */
/*****************************************************************/
{
strcpy(ibuf+35,"INTEGER");
length = length - 4;
fwrite(ibuf,length,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + length + 2;
}
/*****************************************************************/
/* if none of above write out the label to the output file */
/*****************************************************************/
else
{
fwrite(ibuf,length,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + length + 2;
}
/*****************************************************************/
/* test for the end of the PDS labels */
/*****************************************************************/
if ((i = strncmp(ibuf,"END",3)) == 0 && length == 3) break;
} while (length > 0);
/* pad out the labels with blanks to multiple of RECORD_BYTES */
for (i=total_bytes;i<RECORD_BYTES*3;i++) fputc(blank,outfile);
}
/*********************************************************************/
/* */
/* subroutine fits_labels - write FITS header to output file */
/* */
/*********************************************************************/
void fits_labels(host)
int host;
{
char ibuf[2048],outstring[80];
unsigned char cr=13,lf=10,blank=32;
short length,nlen,total_bytes,line,i;
do
{
length = read_var(ibuf,host);
/*****************************************************************/
/* read to the end of the PDS labels */
/*****************************************************************/
if ((i = strncmp(ibuf,"END",3)) == 0 && length == 3) break;
} while (length > 0);
total_bytes = 0;
strcpy(outstring,
"SIMPLE = T
");
fwrite(outstring,78,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + 80;
strcpy(outstring,
"BITPIX = 8
");
fwrite(outstring,78,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + 80;
strcpy(outstring,
"NAXIS = 2
");
fwrite(outstring,78,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + 80;
strcpy(outstring,
"NAXIS1 = 800
");
fwrite(outstring,78,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + 80;
strcpy(outstring,
"NAXIS2 = 800
");
fwrite(outstring,78,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + 80;
strcpy(outstring,
"END
");
fwrite(outstring,78,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + 80;
/* pad out the labels with blanks to multiple of RECORD_BYTES */
for (i=total_bytes;i<2880;i++) fputc(blank,outfile);
}
/*********************************************************************/
/* */
/* subroutine vicar_labels - write vicar labels to output file */
/* (really, really shouldn't assume 800x800 */
/*********************************************************************/
void vicar_labels(host)
int host;
{
char ibuf[2048],outstring[80];
unsigned char cr=13,lf=10,blank=32;
short length,nlen,total_bytes,line,i;
do
{
length = read_var(ibuf,host);
/*****************************************************************/
/* read to the end of the PDS labels */
/*****************************************************************/
if ((i = strncmp(ibuf,"END",3)) == 0 && length == 3) break;
} while (length > 0);
total_bytes = 0;
strcpy(outstring,
"LBLSIZE=800 FORMAT='BYTE' TYPE='IMAGE' BUFSIZ=800 DIM=2 ");
fwrite(outstring,72,1,outfile);
total_bytes = total_bytes + 72;
strcpy(outstring,
"EOL=0 RECSIZE=800 ORG='BSQ' NL=800 NS=800 NB=1 N1=0 N2=0 N3=0 ");
total_bytes = total_bytes + 71;
fwrite(outstring,71,1,outfile);
strcpy(outstring,
"N4=0 NBB=0 NLB=0");
fwrite(outstring,18,1,outfile);
fprintf(outfile,"%c%c",cr,lf);
total_bytes = total_bytes + 20;
/* pad out the labels with blanks to multiple of RECORD_BYTES */
for (i=total_bytes;i<800;i++) fputc(blank,outfile);
}
/*********************************************************************/
/* */
/* subroutine no_labels - read past the pds labels */
/* */
/*********************************************************************/
void no_labels(host)
int host;
{
char ibuf[2048],outstring[80];
unsigned char cr=13,lf=10,blank=32;
short length,nlen,total_bytes,line,i;
do
{
length = read_var(ibuf,host);
/*****************************************************************/
/* read to the end of the PDS labels */
/*****************************************************************/
if ((i = strncmp(ibuf,"END",3)) == 0 && length == 3) break;
} while (length > 0);
}
/*********************************************************************/
/* */
/* subroutine read_var - read variable length records from input file*/
/* */
/*********************************************************************/
read_var(ibuf,host)
char *ibuf;
int host;
{
int length,result,nlen;
char temp;
union /* this union is used to swap 16 and 32 bit integers */
{
char ichar[4];
short slen;
long llen;
} onion;
switch (host)
{
case 1: /*******************************************************/
/* IBM PC host */
/*******************************************************/
length = 0;
result = read(infile,&length,2);
nlen = read(infile,ibuf,length+(length%2));
return (length);
break;
case 2: /*******************************************************/
/* Macintosh host */
/*******************************************************/
length = 0;
result = read(infile,onion.ichar,2);
/* byte swap the length field */
temp = onion.ichar[0];
onion.ichar[0]=onion.ichar[1];
onion.ichar[1]=temp;
length = onion.slen; /* left out of earlier versions */
/* printf("length=%04x,result=%d\n",length,result); */
nlen = read(infile,ibuf,length+(length%2));
return (length);
break;
case 3: /*******************************************************/
/* VAX host with variable length support */
/*******************************************************/
length = read(infile,ibuf,RECORD_BYTES);
return (length);
case 4: /*******************************************************/
/* VAX host, but not a variable length file */
/*******************************************************/
length = 0;
result = read(infile,&length,2);
nlen = read(infile,ibuf,length+(length%2));
/* check to see if we crossed a vax record boundary */
while (nlen < length)
nlen += read(infile,ibuf+nlen,length+(length%2)-nlen);
return (length);
break;
case 5: /*******************************************************/
/* Unix workstation host (non-byte-swapped 32 bit host)*/
/*******************************************************/
length = 0;
result = read(infile,onion.ichar,2);
/* byte swap the length field */
temp = onion.ichar[0];
onion.ichar[0]=onion.ichar[1];
onion.ichar[1]=temp;
length = onion.slen;
/* printf("length=%04x,result=%d\n",length,result); */
nlen = read(infile,ibuf,length+(length%2));
return (length);
break;
}
}
/*********************************************************************/
/* */
/* subroutine check_host - find out what kind of machine we are on */
/* */
/*********************************************************************/
int check_host()
{
/* This subroutine checks the attributes of the host computer and
returns a host code number.
*/
char hostname[80];
int swap,host,bits,var;
union
{
char ichar[2];
short ilen;
} onion;
if (sizeof(var) == 4) bits = 32;
else bits = 16;
onion.ichar[0] = 1;
onion.ichar[1] = 0;
if (onion.ilen == 1) swap = TRUE;
else swap = FALSE;
if (bits == 16 && swap == TRUE)
{
host = 1; /* IBM PC host */
strcpy(hostname,
"Host 1 - 16 bit integers with swapping, no var len support.");
}
if (bits == 16 && swap == FALSE)
{
host = 2; /* Non byte swapped 16 bit host */
strcpy(hostname,
"Host 2 - 16 bit integers without swapping, no var len support.");
}
if (bits == 32 && swap == TRUE)
{ host = 3; /* VAX host with var length support */
strcpy(hostname,
"Host 3,4 - 32 bit integers with swapping.");
}
if (bits == 32 && swap == FALSE)
{
host = 5; /* OTHER 32-bit host */
strcpy(hostname,
"Host 5 - 32 bit integers without swapping, no var len support.");
}
if ((Argc >= 3) && (*outname != '-')) /* suppress if stdout (-) on cmdline */
fprintf(stderr,"%s\n",hostname);
return(host);
}
long swap_long(inval) /* swap 4 byte integer */
long inval;
{
union /* this union is used to swap 16 and 32 bit integers */
{
char ichar[4];
short slen;
long llen;
} onion;
char temp;
/* byte swap the input field */
onion.llen = inval;
temp = onion.ichar[0];
onion.ichar[0]=onion.ichar[3];
onion.ichar[3]=temp;
temp = onion.ichar[1];
onion.ichar[1]=onion.ichar[2];
onion.ichar[2]=temp;
return (onion.llen);
}
void decompress(ibuf,obuf,nin,nout)
/****************************************************************************
*_TITLE decompress - decompresses image lines stored in compressed format *
*_ARGS TYPE NAME I/O DESCRIPTION */
char *ibuf; /* I Compressed data buffer */
char *obuf; /* O Decompressed image line */
long int *nin; /* I Number of bytes on input buffer */
long int *nout; /* I Number of bytes in output buffer */
{
/* The external root pointer to tree */
extern NODE *tree;
/* Declare functions called from this routine */
void dcmprs();
/*************************************************************************
This routine is fairly simple as it's only function is to call the
routine dcmprs.
**************************************************************************/
dcmprs(ibuf,obuf,nin,nout,tree);
return;
}
void decmpinit(hist)
/***************************************************************************
*_TITLE decmpinit - initializes the Huffman tree *
*_ARGS TYPE NAME I/O DESCRIPTION */
long int *hist; /* I First-difference histogram. */
{
extern NODE *tree; /* Huffman tree root pointer */
/* Specify the calling function to initialize the tree */
NODE *huff_tree();
/****************************************************************************
Simply call the huff_tree routine and return.
*****************************************************************************/
tree = huff_tree(hist);
return;
}
NODE *huff_tree(hist)
/****************************************************************************
*_TITLE huff_tree - constructs the Huffman tree; returns pointer to root *
*_ARGS TYPE NAME I/O DESCRIPTION */
long int *hist; /* I First difference histogram */
{
/* Local variables used */
long int freq_list[512]; /* Histogram frequency list */
NODE **node_list; /* DN pointer array list */
register long int *fp; /* Frequency list pointer */
register NODE **np; /* Node list pointer */
register long int num_freq; /* Number non-zero frequencies in
histogram */
long int sum; /* Sum of all frequencies */
register short int num_nodes; /* Counter for DN initialization */
register short int cnt; /* Miscellaneous counter */
short int znull = -1; /* Null node value */
register NODE *temp; /* Temporary node pointer */
/* Functions called */
void sort_freq();
NODE *new_node();
char *malloc();
/***************************************************************************
Allocate the array of nodes from memory and initialize these with numbers
corresponding with the frequency list. There are only 511 possible
permutations of first difference histograms. There are 512 allocated
here to adhere to the FORTRAN version.
****************************************************************************/
fp = freq_list;
node_list = (NODE **) malloc(sizeof(temp)*512);
if (node_list == NULL)
{
fprintf(stderr,"\nOut of memory in huff_tree!\n");
exit(1);
}
np = node_list;
for (num_nodes=1, cnt=512 ; cnt-- ; num_nodes++)
{
/**************************************************************************
The following code has been added to standardize the VAX byte order
for the "long int" type. This code is intended to make the routine
as machine independant as possible.
***************************************************************************/
unsigned char *cp = (unsigned char *) hist++;
unsigned long int j;
short int i;
for (i=4 ; --i >= 0 ; j = (j << 8) | *(cp+i));
/* Now make the assignment */
*fp++ = j;
temp = new_node(num_nodes);
*np++ = temp;
}
(*--fp) = 0; /* Ensure the last element is zeroed out. */
/***************************************************************************
Now, sort the frequency list and eliminate all frequencies of zero.
****************************************************************************/
num_freq = 512;
sort_freq(freq_list,node_list,num_freq);
fp = freq_list;
np = node_list;
for (num_freq=512 ; (*fp) == 0 && (num_freq) ; fp++, np++, num_freq--);
/***************************************************************************
Now create the tree. Note that if there is only one difference value,
it is returned as the root. On each interation, a new node is created
and the least frequently occurring difference is assigned to the right
pointer and the next least frequency to the left pointer. The node
assigned to the left pointer now becomes the combination of the two
nodes and it's frequency is the sum of the two combining nodes.
****************************************************************************/
for (temp=(*np) ; (num_freq--) > 1 ; )
{
temp = new_node(znull);
temp->right = (*np++);
temp->left = (*np);
*np = temp;
*(fp+1) = *(fp+1) + *fp;
*fp++ = 0;
sort_freq(fp,np,num_freq);
}
return temp;
}
NODE *new_node(value)
/****************************************************************************
*_TITLE new_node - allocates a NODE structure and returns a pointer to it *
*_ARGS TYPE NAME I/O DESCRIPTION */
short int value; /* I Value to assign to DN field */
{
NODE *temp; /* Pointer to the memory block */
char *malloc(); /* Memory allocation function */
/***************************************************************************
Allocate the memory and intialize the fields.
****************************************************************************/
temp = (NODE *) malloc(sizeof(NODE));
if (temp != NULL)
{
temp->right = NULL;
temp->dn = value;
temp->left = NULL;
}
else
{
fprintf(stderr,"\nOut of memory in new_node!\n");
exit(1);
}
return temp;
}
void sort_freq(freq_list,node_list,num_freq)
/****************************************************************************
*_TITLE sort_freq - sorts frequency and node lists in increasing freq. order*
*_ARGS TYPE NAME I/O DESCRIPTION */
long int *freq_list; /* I Pointer to frequency list */
NODE **node_list; /* I Pointer to array of node pointers */
long int num_freq; /* I Number of values in freq list */
{
/* Local Variables */
register long int *i; /* primary pointer into freq_list */
register long int *j; /* secondary pointer into freq_list */
register NODE **k; /* primary pointer to node_list */
register NODE **l; /* secondary pointer into node_list */
long int temp1; /* temporary storage for freq_list */
NODE *temp2; /* temporary storage for node_list */
register long int cnt; /* count of list elements */
/************************************************************************
Save the current element - starting with the second - in temporary
storage. Compare with all elements in first part of list moving
each up one element until the element is larger. Insert current
element at this point in list.
*************************************************************************/
if (num_freq <= 0) return; /* If no elements or invalid, return */
for (i=freq_list, k=node_list, cnt=num_freq ; --cnt ; *j=temp1, *l=temp2)
{
temp1 = *(++i);
temp2 = *(++k);
for (j = i, l = k ; *(j-1) > temp1 ; )
{
*j = *(j-1);
*l = *(l-1);
j--;
l--;
if ( j <= freq_list) break;
}
}
return;
}
void dcmprs(ibuf,obuf,nin,nout,root)
/****************************************************************************
*_TITLE dcmprs - decompresses Huffman coded compressed image lines *
*_ARGS TYPE NAME I/O DESCRIPTION */
char *ibuf; /* I Compressed data buffer */
char *obuf; /* O Decompressed image line */
long int *nin; /* I Number of bytes on input buffer */
long int *nout; /* I Number of bytes in output buffer */
NODE *root; /* I Huffman coded tree */
{
/* Local Variables */
register NODE *ptr = root; /* pointer to position in tree */
register unsigned char test; /* test byte for bit set */
register unsigned char idn; /* input compressed byte */
register char odn; /* last dn value decompressed */
char *ilim = ibuf + *nin; /* end of compressed bytes */
char *olim = obuf + *nout; /* end of output buffer */
/**************************************************************************
Check for valid input values for nin, nout and make initial assignments.
***************************************************************************/
if (ilim > ibuf && olim > obuf)
odn = *obuf++ = *ibuf++;
else
{
fprintf(stderr,"\nInvalid byte count in dcmprs!\n");
exit(1);
}
/**************************************************************************
Decompress the input buffer. Assign the first byte to the working
variable, idn. An arithmatic and (&) is performed using the variable
'test' that is bit shifted to the right. If the result is 0, then
go to right else go to left.
***************************************************************************/
for (idn=(*ibuf) ; ibuf < ilim ; idn =(*++ibuf))
{
for (test=0x80 ; test ; test >>= 1)
{
ptr = (test & idn) ? ptr->left : ptr->right;
if (ptr->dn != -1)
{
if (obuf >= olim) return;
odn -= ptr->dn + 256;
*obuf++ = odn;
ptr = root;
}
}
}
return;
}
void free_tree(nfreed)
/****************************************************************************
*_TITLE free_tree - free memory of all allocated nodes *
*_ARGS TYPE NAME I/O DESCRIPTION */
long int *nfreed; /* O Return of total count of nodes *
* freed. */
/*
*_DESCR This routine is supplied to the programmer to free up all the *
* allocated memory required to build the huffman tree. The count *
* of the nodes freed is returned in the parameter 'nfreed'. The *
* purpose of the routine is so if the user wishes to decompress more *
* than one file per run, the program will not keep allocating new *
* memory without first deallocating all previous nodes associated *
* with the previous file decompression. *
*_HIST 16-AUG-89 Kris Becker USGS, Flagstaff Original Version *
*_END *
****************************************************************************/
{
long int total_free = 0;
extern NODE *tree; /* Huffman tree root pointer */
/* Specify the function to free the tree */
long int free_node();
/****************************************************************************
Simply call the free_node routine and return the result.
*****************************************************************************/
*nfreed = free_node(tree,total_free);
return;
}
long int free_node(pnode,total_free)
/***************************************************************************
*_TITLE free_node - deallocates an allocated NODE pointer
*_ARGS TYPE NAME I/O DESCRIPTION */
NODE *pnode; /* I Pointer to node to free */
long int total_free; /* I Total number of freed nodes */
/*
*_DESCR free_node will check both right and left pointers of a node *
* and then free the current node using the free() C utility. *
* Note that all nodes attached to the node via right or left *
* pointers area also freed, so be sure that this is the desired *
* result when calling this routine. *
* This routine is supplied to allow successive calls to the *
* decmpinit routine. It will free up the memory allocated *
* by previous calls to the decmpinit routine. The call to free *
* a previous huffman tree is: total = free_node(tree,(long) 0); *
* This call must be done by the programmer application routine *
* and is not done by any of these routines. *
*_HIST 16-AUG-89 Kris Becker U.S.G.S Flagstaff Original Version */
{
if (pnode == (NODE *) NULL) return(total_free);
if (pnode->right != (NODE *) NULL)
total_free = free_node(pnode->right,total_free);
if (pnode->left != (NODE *) NULL)
total_free = free_node(pnode->left,total_free);
free((char *) pnode);
return(total_free + 1);
}
@//E*O*F pdsuncomp.c//
chmod u=rw,g=r,o=r pdsuncomp.c
echo x - xvpds.c
sed 's/^@//' > "xvpds.c" <<'@//E*O*F xvpds.c//'
/*
* xvpds.c - load routine for astronomical PDS/VICAR format pictures
*
* Anthony A. Datri
* Convex Computer Corp
* 3000 Waterview Parkway
* Ricardson, TX 75080
* datri@convex.com
*
* 9-2-91 began integration. Much of this code is lifted from vicar.c,
* which I wrote for xloadimage. This is a little simpler, though.
* code to identify and read in PDS/VICAR images, as found on the CD-ROMS from
* NASA, and on ames.arc.nasa.gov.
*
* 10-17-91 pdsuncomp is called with system(), which typically feeds the
* commandline to sh. Make sure that your .profile adds wherever
* you have pdsuncomp to the PATH, like
*
* PATH=$PATH:/usr/local/bin
*
*
* Sources of these CD's:
*
* National Space Science Data Center
* Goddard Space Flight Center
* Code 933.4
* Greenbelt, Maryland
* (301) 286-6695
* or call
* (301) 286-9000 (300,1200,2400 bps)
* or telnet
* nssdca.gsfc.nasa.gov (128.183.10.4) and log in as 'NODIS' (no password).
*
* Randy Davis
* LASP
* University of Colorado
* Boulder CO 80309-0392
* (303) 492-6867
* These CD's are reasonably priced. Encourage the continue production
* of them by buying a set.
* There are three types of files that we deal with here. I'll call them
* PDS-labeled, PDS-labeled Huffman-encoded, and VICAR. Each consists of data
* prefixed with a set of ASCII headers. PDS-labeled and VICAR files are raw
* grayscale data, the dimensions of which can be found from the headers.
* PDS-labeled, Huffman-encoded files have the image information adaptively
* Huffman-encoded, and the encoding histogram follows the ASCII headers.
* To decode these, we use an extended version of "cdcomp.c" from the
* NASA Vger CD-ROMS. For this to work, you need to have pdscomp compiled
* and in your path. pdscomp.c should be included with this distribution.
* I've heard that newer discs have FITS images on them. If they do, support
* for them will be added when I get one. Until then, you can use fitstopgm.
*
* strstr is used extensively here. If your machine doesn't have strstr,
* you need to do two things:
*
* o uncomment the STRSTRF def in the Makefile to get a free version
* o beat up your vendor for not giving it to you
*
* SunOS didn't have it until 4.1, for example
*
*
* LoadPDS(fname, numcols) - coerces a PDS/VICAR image
* WriteVICAR(fp, pic, w, h, r,g,b, numcols, style)
*/
/*
* Copyright 1989, 1990 by Anthony A. Datri
*
* Permission to use, copy, and distribute for non-commercial purposes,
* is hereby granted without fee, providing that the above copyright
* notice appear in all copies and that both the copyright notice and this
* permission notice appear in supporting documentation.
*
* This software is provided "as is" without any express or implied warranty.
*/
#include "xv.h"
#ifndef TRUE
#define TRUE (1)
#define FALSE (0)
#endif
#define PDSFIXED (1)
#define PDSVARIABLE (2)
#define PDSTRASH (-1)
#define VICAR (3)
#define MAX_SIZE 20480 /*10240*/ /* a guess -- even magellan images aren't
bigger than 2k x 2k */
#define RTBUFFSIZE 20 /* small buffer for magic */
#define FNAMESIZE 1024 /* too hard to generalize really getting it */
#define PDSUNCOMP "pdsuncomp" /* filter to un-Huffmanize */
/* This is arbitrary. Everything I've seen so far fits */
#define COMMENTSIZE 50
static char scanbuff[MAX_SIZE], rtbuff[RTBUFFSIZE], infobuff[COMMENTSIZE],
spacecraft[COMMENTSIZE],
target[COMMENTSIZE],
filtname[COMMENTSIZE],
mphase[COMMENTSIZE],
iname[COMMENTSIZE],
itime[COMMENTSIZE],
pdsuncompfname[FNAMESIZE];
byte *image;
/* here's an strstr for the libc-impaired */
#ifdef NOSTRSTR
/*
* strstr.c --
*
* Source code for the "strstr" library routine.
*
* Copyright 1988 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/lib/c/string/RCS/strstr.c,v
1.2 89/03/22 16:07:57 rab Exp $ SPRITE (Berkeley)";
#endif /* not lint */
/*
*----------------------------------------------------------------------
*
* strstr --
*
* Locate the first instance of a substring in a string.
*
* Results:
* If string contains substring, the return value is the
* location of the first matching instance of substring
* in string. If string doesn't contain substring, the
* return value is 0. Matching is done on an exact
* character-for-character basis with no wildcards or special
* characters.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
char *
strstr(string, substring)
char *string; /* String to search. */
char *substring; /* Substring to try to find in string. */
{
register char *a, *b;
/* First scan quickly through the two strings looking for a
* single-character match. When it's found, then compare the
* rest of the substring.
*/
b = substring;
if (*b == 0) {
return string;
}
for ( ; *string != 0; string += 1) {
if (*string != *b) {
continue;
}
a = string;
while (1) {
if (*b == 0) {
return string;
}
if (*a++ != *b++) {
break;
}
}
b = substring;
}
return (char *) 0;
}
#endif /* NOSTRSTR */
/* get a NULL-, CR-, or CRLF-terminated record from a PDS file */
/* The method of termination is unpredictable. A pox on VMS */
int getpdsrec(f,buff)
FILE *f;
char *buff; {
static char *bp;
static int count;
count=0;
bp=buff;
for (;TRUE;) {
(*bp)=fgetc(f);
switch (*bp) {
case '\r':
*bp='\0';
switch ((*(bp+1))=fgetc(f)) {
case EOF:
case '\n':
break;
default:
ungetc(*(bp+1),f);
}
return(count);
case EOF:
*bp='\0';
return(count);
case '\0':
return(count);
default:
count++;
bp++;
}
}
}
/* A VICAR image seems to begin with a one-line header describing all sorts
* of things, almost all of which don't mean much to Joe User, who just
* wants to see what Venus looks like. The first thing in this label is a
* string defining the size of the label, like "LBLSIZE=2048". Then there's
* other crud of variable usefulness. Important to us are the NL and NS
* fields, which seem to tell us the number of columns and rows, respectively.
* Among these other fields seem to be the local map coordinates of the region.
* These files are easy -- you can even convert one to usefulness by grabbing
* the dimensions and lblsize and feeding to rawtopgm. For example, if
lblsize,
* nl, and ns are 2048, 1536, and 2048, respectively, use "rawtopgm -headerskip
* 2048 2048 1536 <foo.img >foo.pgm. All of the samples I've seen are 8 bits
* deep, so we assume that. Yeah, yeah, that's nasty and evil, and I'm
* terribly ashamed of it, but I'm not going to bother with bit fiddling
* until I see an image that requires it
*
* These images are typically fairly big, so it makes sense to verify the
* format before we try to read it all in.
*
* PDS images are prefixed like this:
*
* od -a c2061139.imq | head -a
* 0000000 - nul N J P L 1 I 0 0 P D S 1 0 0
*
* so we'll read off the first two chars, which seem to be a length field
* of some kind, then look for NJPL.. But NOOOOOO, images on the Sampler
* disc just HAVE to leave off the first two bytes. Bloody HELL! This
* is the distinction between the fixed and variable-record files.
*/
/*******************************************/
int LoadPDS(fname,nc)
char *fname;
int nc; {
int tempnum;
FILE *zf;
static int isfixed,teco,i,j,itype,lastwasinote,
recsize,hrecsize,irecsize,isimage,labelrecs,labelsofar,
x,y,lpsize,lssize,samplesize,returnp,labelsize,yy;
char *tmp;
isfixed=TRUE;
returnp=isimage=FALSE;
itype=PDSTRASH;
teco=i=j=recsize=hrecsize=irecsize=labelrecs=x=y=lpsize=lssize=
samplesize=labelsize=labelsofar=0;
(*pdsuncompfname)=(*iname)=(*target)=(*filtname)=(*itime)=(*spacecraft)=(*scanb
uff)=
(*mphase)=(*rtbuff)='\0';
/* there may be some wisdom in statically mallocing space for an 800x800
image, since that's what the Voyager cd's have, or even a 2kx2k, since
some of the Magellan images from ames are that size */
zf=fopen(fname,"r");
if (!zf) {
SetISTR(ISTR_INFO,"LoadPDS: can't open %s\n",fname);
return(1);
}
/* read the magic. If it's got two bytes of crud in front of it, it's
a damned "variable-length-record" file, and we have to jump through
bloody VAX hoops, and feed it through pdsuncomp to get useful bits */
if ((teco=fread(rtbuff,13,1,zf)) != 1) {
SetISTR(ISTR_INFO,"LoadPDS: couldn't read magic: %d,%s",teco,fname);
Warning();
fclose(zf);
return(1);
}
rtbuff[13]='\0'; /* this makes sscanf so much happier */
if ((strncmp(rtbuff, "NJPL1I00PDS",11) == 0) ||
((isfixed=strncmp(rtbuff+2,"NJPL1I00PDS",11)) == 0)) {
/* we only handle 8 b/p right now */
SetISTR(ISTR_FORMAT, isfixed ? "PDS/VICAR, 8 bits per pixel." :
"Huffman-encoded PDS, 8 bits per pixel.");
if (!(isfixed)) {
teco = ((*rtbuff) + ((*(rtbuff+1)) << 8));
fread(rtbuff,(teco % 2 ? teco + 1 : teco ) - 11,1,zf);
}
/* we know that we've got a PDS file of some sort. We have to
search through the labels looking for things because usage doesn't seem
to be consistent, or even predictable. When I added this format to
xloadimage, I had the code spew out various peices of information, like
the name of the target, filter used, etc. Xv, however, doesn't really
provide precedent for this kind of thing, and I can't really stick it
into the info box without overhauling it. Maybe later I'll add a
-verbose switch which this module will interpret as license to scribble
on stdout or stderr */
for (;;) {
if (isfixed) {
if (getpdsrec(zf,scanbuff) == 0) {
SetISTR(ISTR_INFO,
"corrupt or incomplete PDS labels (low fread)");
Warning();
break;
}
} else {
/* AAAARGGGGH! We've got a bloody variable-length file where
* the headers are preceded by a byte count, as a VAX 16-bit
* integer of all things. VMS: Just Say NFW.
* "A compressed image file is composed of variable-length records
* defined according to the ISO standard. Each variable length
* record starts with a record length indicator, stored as a 16-bit
* integer, followed by the number of bytes indicated in the record
* length indicator. If the length indicator is odd, then a pad byte
* is appended to the end of the record so that all records contain
* an even number of bytes."*/
i=getc(zf);
j=getc(zf);
if (j == EOF) {
SetISTR(ISTR_INFO,"LoadPDS: j is EOF\n");
fclose(zf);
return(1);
}
teco = i + (j << 8);
if (teco % 2) {
teco++;
}
if (fread(scanbuff,teco,1,zf) != 1) {
SetISTR(ISTR_INFO,"LoadPDS: bad fread reading labels\n");
fclose(zf);
return(1);
}
scanbuff[teco]='\0';
}
/* otay, we've managed to wrestle a header of some sort from the
file -- now we grep through until we hit the END, at which point
we break out of the loop and see what we've got. In the future,
we'll check for informational headers and write them out if the
fool user wants them. There seems to be disagreement about what
the headers are called, since we might find, for example, either
TARGET_BODY or TARGET_NAME. Bloody 'ell. */
if (strcmp(scanbuff,"END") == 0) {
break;
} else if (sscanf(scanbuff,"RECORD_TYPE = %s",rtbuff) == 1) {
if (strncmp(rtbuff,"VARIABLE_LENGTH",15) == 0) {
itype=PDSVARIABLE;
} else if (strncmp(rtbuff,"FIXED_LENGTH",12) == 0) {
itype=PDSFIXED;
} else {
rtbuff[RTBUFFSIZE-1]='\0'; /* juuuust in case */
SetISTR(ISTR_INFO,
"LoadPDS: unsupported record type \"%s\"\n",rtbuff);
fclose(zf);
return(1);
}
} else if (sscanf(scanbuff,"RECORD_BYTES = %d",&recsize) == 1) {
/* these default to RECORD_BYTES unless explicitly set */
if (hrecsize == 0)
hrecsize=recsize;
if (irecsize == 0)
irecsize=recsize;
continue;
} else if (sscanf(scanbuff,"FILE_TYPE = %s", rtbuff) != NULL) {
if (strncmp(rtbuff,"IMAGE",5) == 0) {
isimage=TRUE;
continue;
} else {
isimage=FALSE;
break;
}
} else if ((sscanf(scanbuff," HEADER_RECORDS = %d",&labelrecs) == 1) ||
(sscanf(scanbuff," LABEL_RECORDS = %d", &labelrecs) == 1)) {
continue;
} else if (sscanf(scanbuff," IMAGE_LINES = %d",&y) == 1) {
isimage=TRUE; continue;
} else if (sscanf(scanbuff," LINE_SAMPLES = %d",&x) == 1) {
continue;
} else if (sscanf(scanbuff," LINES = %d",&y) == 1) {
isimage=TRUE; continue;
} else if (sscanf(scanbuff," HEADER_RECORD_BYTES = %d",&hrecsize)==1) {
continue;
} else if (sscanf(scanbuff," IMAGE_RECORD_BYTES = %d",&irecsize)==1) {
continue;
} else if (sscanf(scanbuff," LINE_PREFIX_BYTES = %d",&lpsize)==1) {
continue;
} else if (sscanf(scanbuff," LINE_SUFFIX_BYTES = %d",&lssize)==1) {
continue;
} else if (sscanf(scanbuff," SAMPLE_BITS = %d", &samplesize) == 1) {
continue;
} else if (sscanf(scanbuff," SPACECRAFT_NAME = %s", spacecraft) == 1) {
continue;
/* } else if (sscanf(scanbuff," MISSION_PHASE_NAME = %s", mphase) == 1) {
continue;
} else if (sscanf(scanbuff," MISSION_PHASE = %s", mphase) == 1) {
continue;*/
} else if (sscanf(scanbuff," TARGET_NAME = %s", target) == 1) {
continue;
} else if (sscanf(scanbuff," TARGET_BODY = %s", target) == 1) {
continue;
/* } else if (sscanf(scanbuff," INSTRUMENT_NAME = %s", iname) == 1) {
continue;*/
} else if (sscanf(scanbuff," SPACECRAFT_EVENT_TIME = %s", itime) == 1) {
continue;
} else if (sscanf(scanbuff," IMAGE_TIME = %s", itime) == 1) {
continue;
} else if (sscanf(scanbuff," FILTER_NAME = %s", filtname) == 1) {
continue;
} else if (sscanf(scanbuff," INSTRUMENT_FILTER_NAME = %s", filtname) == 1) {
continue;
}
/* I never did understand any of these
} else if (sscanf(scanbuff," GAIN_MODE_ID = %s", gainmode) == 1) {
continue;
} else if (sscanf(scanbuff," INSTRUMENT_GAIN_STATE = %s", gainmode) == 1) {
continue;
} else if (sscanf(scanbuff," EDIT_MODE_ID = %s", editmode) == 1) {
continue;
} else if (sscanf(scanbuff," INSTRUMENT_EDIT_MODE = %s", editmode) == 1) {
continue;
} else if (sscanf(scanbuff," SCAN_MODE_ID = %s", scanmode) == 1) {
continue;
} else if (sscanf(scanbuff," INSTRUMENT_SCAN_RATE = %s", scanmode) == 1) {
continue;
} else if (sscanf(scanbuff," SHUTTER_MODE_ID = %s", shutmode) == 1) {
continue;
} else if (sscanf(scanbuff," INSTRUMENT_SHUTTER_MODE = %s", shutmode) == 1) {
continue; */
}
if ((isimage == TRUE) && (labelsize=(labelrecs * hrecsize))) {
if (samplesize!= 8) {
SetISTR(ISTR_INFO,"This image looks to be %d bits deep, but I can
only handle 8-bit PDS files\n");
fclose(zf);
return(1);
}
} else {
SetISTR(ISTR_INFO,"This looks a lot like a PDS/VICAR image, but I can't
see the size of the label\n");
fclose(zf);
return(1);
}
/* Some day this should be generalized to read <>8-bit files. If I ever find
* one that's interesting, I'll do the work. */
} else if (sscanf(rtbuff,"LBLSIZE = %d%n",&labelsize,&labelsofar) == 1) {
/* we've got a VICAR file. Let's find out how big the puppy is */
itype=VICAR;
if (fread(scanbuff,labelsize-labelsofar,1,zf) == 1) {
if ((tmp=strstr(scanbuff,"NL=")) == NULL) {
SetISTR(ISTR_INFO,"LoadPDS: bad NL in VICAR\n");
returnp=TRUE;
}
if (sscanf(tmp,"NL = %d",&y) != 1) {
SetISTR(ISTR_INFO,"LoadPDS: bad scan NL in VICAR\n");
returnp=TRUE;
}
if ((tmp=strstr(scanbuff, "NS=")) == NULL) {
SetISTR(ISTR_INFO,"LoadPDS: bad NS in VICAR\n");
returnp=TRUE;
}
if (sscanf(tmp, "NS = %d",&x) != 1) {
SetISTR(ISTR_INFO,"LoadPDS: bad scan NS in VICAR\n");
returnp=TRUE;
}
}
} else {
SetISTR(ISTR_INFO,"LoadPDS: I guess this isn't one of mine after all\n");
returnp=TRUE;
}
if (returnp) {
fclose(zf);
return(1);
}
/* PDS files tend to have lots of information like this in them. The
* following are a few of the more interesting headers. We'd do more, but
* there's only so much space in the info box */
*infobuff='\0';
if (*spacecraft) {
strcat(infobuff,spacecraft);
}
if (*target) {
strcat(infobuff,", ");
strcat(infobuff,target);
}
if (*filtname) {
strcat(infobuff,", ");
strcat(infobuff,filtname);
}
if (*itime) {
strcat(infobuff,", ");
strcat(infobuff,itime);
}
SetISTR(ISTR_WARNING,infobuff);
strcpy(pdsuncompfname,fname);
switch (itype) {
case VICAR:
SetISTR(ISTR_FORMAT, "VICAR, 8 bits per pixel.");
rewind(zf);
break;
case PDSFIXED:
SetISTR(ISTR_FORMAT, "PDS, 8 bits per pixel.");
rewind(zf);
break;
case PDSVARIABLE:
SetISTR(ISTR_FORMAT, "PDS, 8 bits per pixel, Huffman-encoded.");
fclose(zf);
/* strcat(fname,".out");*/
strcpy(pdsuncompfname,"/tmp/xvhuffXXXXXX");
mktemp(pdsuncompfname);
sprintf(scanbuff,"%s %s - 4 >%s",PDSUNCOMP,fname,pdsuncompfname);
SetISTR(ISTR_INFO,"De-Huffmanizing '%s'...",fname);
/* pdsuncomp filters to a raw file */
if (tempnum=system(scanbuff)) {
SetISTR(ISTR_INFO,"Unable to de-Huffmanize '%s'.",fname);
/*fprintf(stderr,"system returned %d\n",tempnum);fflush(stderr);*/
Warning();
return(1);
}
fprintf(stderr,"system returned %d\n",tempnum);fflush(stderr);
zf=fopen(pdsuncompfname,"r");
if (!zf) {
SetISTR(ISTR_INFO,"LoadPDS: can't open uncompressed file %s\n",
pdsuncompfname);
Warning();
return(1);
}
}
/* skip headers */
if (itype != PDSVARIABLE) {
fread(scanbuff,labelsize,1,zf);
}
image=(byte *)malloc(x*y);
if (image == NULL) {
SetISTR(ISTR_INFO,"LoadPDS: couldn't malloc %d",x*y);
Warning();
fclose(zf);
if (itype==PDSVARIABLE)
unlink(pdsuncompfname);
exit(1);
}
if ((lssize || lpsize) & (itype == PDSFIXED)) {
/* ARrrrgh. Some of these images have crud intermixed with the image, */
/* preventing us from freading in one fell swoop (whatever a fell
swoop is */
for (yy=0;yy<y;yy++) {
if (lpsize && ((teco=(fread(scanbuff,lpsize,1,zf))) != 1)) {
SetISTR(ISTR_INFO, "LoadPDS: unexpected EOF reading prefix");
Warning();
fclose(zf);
return(1);
}
if ((teco=(fread(image+(yy*x),x,1,zf))) != 1) {
SetISTR(ISTR_INFO, "LoadPDS: unexpected EOF reading line %d",yy);
Warning();
fclose(zf);
return(1);
}
if (lssize && ((teco=(fread(scanbuff,lssize,1,zf))) != 1)) {
SetISTR(ISTR_INFO, "LoadPDS: unexpected EOF reading suffix");
Warning();
fclose(zf);
return(1);
}
}
} else if ((yy=fread(image,x*y,1,zf)) != 1) {
SetISTR(ISTR_INFO,"LoadPDS: error reading image data");
Warning();
fclose(zf);
if (itype==PDSVARIABLE)
unlink(pdsuncompfname);
return(1);
}
/*SetISTR(ISTR_INFO,infobuff);*/
fclose(zf);
if (itype==PDSVARIABLE)
unlink(pdsuncompfname);
/* fix up xv globals */
pic = image;
pWIDE = x;
pHIGH = y;
/* these are grayscale, so cobble up a ramped colormap */
for (yy=0; yy<=255; yy++) {
/* *(r+yy)=*(g+yy)=*(b+yy)=yy;*/
*(r+yy)=yy;
}
/* this is cheating, but saves a few hundred ops */
memcpy(g,r,256*(sizeof(byte)));
memcpy(b,r,256*(sizeof(byte)));
return(0);
}
@//E*O*F xvpds.c//
chmod u=rw,g=r,o=r xvpds.c
exit 0
(Message /usr/users/bradley/Mail/inbox:15)
Return-Path: beser@aplcomm.jhuapl.edu
Received-Date: Wed, 13 Nov 91 16:52:37 EST
Received: from aplcomm.jhuapl.edu by central.cis.upenn.edu
id AA16950; Wed, 13 Nov 91 16:52:35 -0500
Posted-Date: Wed, 13 Nov 91 16:52:51 -0500
Received: by aplcomm.jhuapl.edu (5.61/4.7)
id AA25505; Wed, 13 Nov 91 16:52:51 -0500
Date: Wed, 13 Nov 91 16:52:51 -0500
From: beser@aplcomm.jhuapl.edu (Nick Beser)
Message-Id: <9111132152.AA25505@aplcomm.jhuapl.edu>
To: bradley@central.cis.upenn.edu
John,
I wanted to let you know that I have found a problem with the vicar
patches that I told you about several weeks ago. I have been attempting to
read the Viking orbiter images with the modified xv program and have discovered
a difference in the header information between different PDS formatted images.
The voyager images have a header that looks like the following:
uvisiss{beser}45: od -a c1072726.imq | more
0000000 - nul N J P L 1 I 0 0 P D S 1 0 0
0000020 0 0 0 0 0 0 sp sp sp sp sp sp sp sp sp sp
0000040 sp sp sp = sp S F D U _ L A B E L nul
0000060 " nul / * sp sp sp sp sp sp sp sp sp sp F I
0000100 L E sp F O R M A T sp A N D sp L E
0000120 N G T H 2 nul R E C O R D _ T Y P
0000140 E sp sp sp sp sp sp sp sp sp sp sp sp sp sp sp
0000160 sp sp sp sp sp sp sp = sp V A R I A B L
0000200 E _ L E N G T H & nul R E C O R D
0000220 _ B Y T E S sp sp sp sp sp sp sp sp sp sp
0000240 sp sp sp sp sp sp sp sp sp sp sp = sp 8 3 6
The Viking Images have a header that looks like:
uvisiss{beser}50: od -a f139s01.imq | more
0000000 5 nul C C S D 3 Z F 0 0 0 0 1 0 0
0000020 0 0 0 0 0 1 N J P L 3 I F 0 P D
0000040 S 2 0 0 0 0 0 0 0 1 sp = sp S F D
0000060 U _ L A B E L nul % nul / * sp sp sp sp
0000100 sp sp sp sp sp sp F I L E sp F O R M A
0000120 T sp A N D sp L E N G T H sp * / nul
0000140 2 nul R E C O R D _ T Y P E sp sp sp
0000160 sp sp sp sp sp sp sp sp sp sp sp sp sp sp sp sp
0000200 sp sp sp = sp V A R I A B L E _ L E
0000220 N G T H ' nul R E C O R D _ B Y T
0000240 E S sp sp sp sp sp sp sp sp sp sp sp sp sp sp
The program has two subroutines that parse the header of the PDS files,
and if it matches the NJPLxx code (in the first 12 bytes of the header,
it calls it a PDS file. It seems that the program should look at more
of the header. The two routines are xv.c and xvpds.c. If you are going
to release a new version of the program I could send you some sample images
from Voyager, Magellan, and Viking so you could confirm that they can be
read. Will you be releasing the code soon? Are you looking for beta testers?
Please let me know as soon as the code is available.
Nick Beser
beser@aplcomm.jhuapl.edu
(Message /usr/users/bradley/Mail/inbox:13)
Return-Path: datri@lovecraft.convex.com
Received-Date: Fri, 22 Nov 91 10:06:05 EST
Received: from convex.convex.com by central.cis.upenn.edu
id AA13501; Fri, 22 Nov 91 10:06:02 -0500
Posted-Date: Fri, 22 Nov 1991 09:05:46 -0600 (CST)
Received: from lovecraft.convex.com by convex.convex.com (5.61/1.35)
id AA27919; Fri, 22 Nov 91 09:05:50 -0600
Received: by lovecraft.convex.com (4.1/SMI-4.1)
id AA09791; Fri, 22 Nov 91 09:05:48 CST
Received: from Messages.7.15.N.CUILIB.3.45.SNAP.NOT.LINKED.lovecraft.convex.com.sun4.41
via MS.5.6.lovecraft.convex.com.sun4_41;
Fri, 22 Nov 1991 09:05:46 -0600 (CST)
Message-Id: <Ad=Fn_G2e4NhIZT1AT@concave>
Date: Fri, 22 Nov 1991 09:05:46 -0600 (CST)
From: "Anthony A. Datri" <datri@concave.convex.com>
To: bradley@central.cis.upenn.edu
Subject: new xv module
I've updated my PDS/VICAR support for xv to handle the format variant
found on the Viking CD-ROMs. This includes a new, more general
decompression program called vdcomp. There's a tar file of patches on
convex.com in pub.